package com.niezhiliang.springboot.rabbitmq.common.util;


import com.alibaba.fastjson.JSON;

import java.text.MessageFormat;
import java.text.SimpleDateFormat;
import java.util.Date;


/**
 * @ClassName Logger
 * @Description 自定义Logger包装类。实际使用的还是slf4j的实现类，只是在使用具体log方法时加入了指定格式的封装，加入了作者信息。
 * @author Ryan
 * @date 2017年11月11日
 */
public class Logger
{

    /**
     * 构造函数私有化
     */
    private Logger(){}
    
    public static Logger getLogger(){
    	try {
			return getLogger(Class.forName(Thread.currentThread().getStackTrace()[2].getClassName()));
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
    	return null;
    }

    protected Author author;

    protected org.slf4j.Logger realLogger;

    /**
     * 自定义内容组合格式：0参数为编码者姓名，1为原class文件2为方法名3为代码行数，4为原内容。 格式化后当使用logger.debug("这是日志内容:{}","Ryan","我")
     */
    private static final String FORMAT = "【{0}】-[{1}:{2}]<{3}>[{4}]: \n  {5}";
    private static final String REMAIN_ERROR_FORMAT = "【{0}】-[{1}:{2}]<{3}>[{4}]: \n【严重警告】  {5}";

    private static final SimpleDateFormat dateFormat = new SimpleDateFormat(
        "yyyy-MM-dd HH:mm:ss.SSS");

    /**
     * @Title formatMsg
     * @Description 将原始log日志加入自定义信息（作者、实际log的类、方法、时间等。）
     * @param msg
     * @return
     */
    protected String formatMsg(String msg)
    {
        StackTraceElement item = Thread.currentThread().getStackTrace()[3];
        return MessageFormat.format(FORMAT, author.nickname(), item.getClassName(),
            item.getMethodName(), item.getLineNumber(), dateFormat.format(new Date()), msg);
    }

    protected String formatRemainErrorMsg(String msg)
    {
        StackTraceElement item = Thread.currentThread().getStackTrace()[3];
        return MessageFormat.format(REMAIN_ERROR_FORMAT, author.nickname(), item.getClassName(),
            item.getMethodName(), item.getLineNumber(), dateFormat.format(new Date()), msg);
    }

    public org.slf4j.Logger getRealLogger()
    {
        return realLogger;
    }

    /**
     * @ClassName LoggerWithAuthor
     * @Description 继承Logger的类，可提前设置作者，通过Logger中的方法转换到此类，不可直接创建实例。
     * @author Ryan
     * @date 2017年11月13日
     */
    public static class LoggerWithAuthor extends Logger
    {

        private LoggerWithAuthor()
        {};

        public void debug(String msg)
        {
            if (realLogger.isDebugEnabled())
            {

                realLogger.debug(formatMsg(msg));
            }
        }

        public void debug(String msg, Object... arguments)
        {
            if (realLogger.isDebugEnabled())
            {

                realLogger.debug(formatMsg(msg), arguments);
            }
        }

        public void debug(String msg, Object arg1, Object arg2)
        {
            if (realLogger.isDebugEnabled())
            {

                realLogger.debug(formatMsg(msg), arg1, arg2);
            }
        }

        public void debug(String msg, Object argument)
        {
            if (realLogger.isDebugEnabled())
            {
            	if(!(argument instanceof String) && !(argument instanceof Integer) 
              			 && !(argument instanceof Integer) 
              			 && !(argument instanceof Long) 
              			 && !(argument instanceof Double) 
              			 && !(argument instanceof Float) 
              			 && !(argument instanceof Boolean) 
              			){
   	           		argument = JSON.toJSONString(argument);
   	           	}
                realLogger.debug(formatMsg(msg), argument);
            }
        }

        public void debug(String msg, Throwable t)
        {
            if (realLogger.isDebugEnabled())
            {

                realLogger.debug(formatMsg(msg), t);
            }
        }

        public void info(String msg)
        {
            if (realLogger.isInfoEnabled())
            {

                realLogger.info(formatMsg(msg));
            }
        }

        public void info(String msg, Object... arguments)
        {
            if (realLogger.isInfoEnabled())
            {

                realLogger.info(formatMsg(msg), arguments);
            }
        }

        public void info(String msg, Object arg1, Object arg2)
        {
            if (realLogger.isInfoEnabled())
            {

                realLogger.info(formatMsg(msg), arg1, arg2);
            }
        }

        public void info(String msg, Object argument)
        {
            if (realLogger.isInfoEnabled())
            {
                realLogger.info(formatMsg(msg), argument);
            }
        }

        public void info(String msg, Throwable t)
        {
            if (realLogger.isInfoEnabled())
            {

                realLogger.info(formatMsg(msg), t);
            }
        }

        public void warn(String msg)
        {
            if (realLogger.isWarnEnabled())
            {

                realLogger.warn(formatMsg(msg));
            }
        }

        public void warn(String msg, Object... arguments)
        {
            if (realLogger.isWarnEnabled())
            {

                realLogger.warn(formatMsg(msg), arguments);
            }
        }

        public void warn(String msg, Object arg1,Throwable t)
        {
            if (realLogger.isWarnEnabled())
            {

                realLogger.warn(formatMsg(msg), arg1,t);
            }
        }

        public void warn(String msg, Object arg1,Object arg2,Throwable t)
        {
            if (realLogger.isWarnEnabled())
            {

                realLogger.warn(formatMsg(msg), arg1,arg2,t);
            }
        }

        public void warn(String msg, Object arg1, Object arg2)
        {
            if (realLogger.isWarnEnabled())
            {

                realLogger.warn(formatMsg(msg), arg1, arg2);
            }
        }

        public void warn(String msg, Object argument)
        {
            if (realLogger.isWarnEnabled())
            {

                realLogger.warn(formatMsg(msg), argument);
            }
        }

        public void warn(String msg, Throwable t)
        {
            if (realLogger.isWarnEnabled())
            {

                realLogger.warn(formatMsg(msg), t);
            }
        }

        public void error(String msg)
        {
            if (realLogger.isErrorEnabled())
            {

                realLogger.error(formatMsg(msg));
            }
        }

        public void error(String msg, Object... arguments)
        {
            if (realLogger.isErrorEnabled())
            {

                realLogger.error(formatMsg(msg), arguments);
            }
        }

        public void error(String msg, Object arg1, Object arg2)
        {
            if (realLogger.isErrorEnabled())
            {

                realLogger.error(formatMsg(msg), arg1, arg2);
            }
        }

        public void error(String msg, Object argument)
        {
            if (realLogger.isErrorEnabled())
            {

                realLogger.error(formatMsg(msg), argument);
            }
        }

        public void error(String msg, Throwable t)
        {
            if (realLogger.isErrorEnabled())
            {

                realLogger.error(formatMsg(msg), t);
            }
        }

        //remainError 需要及时解决的问题
        public void remainError(String msg)
        {
            if (realLogger.isErrorEnabled())
            {

                realLogger.error(formatRemainErrorMsg(msg));
            }
        }

        public void remainError(String msg, Object... arguments)
        {
            if (realLogger.isErrorEnabled())
            {

                realLogger.error(formatRemainErrorMsg(msg), arguments);
            }
        }

        public void remainError(String msg, Object arg1, Object arg2)
        {
            if (realLogger.isErrorEnabled())
            {

                realLogger.error(formatRemainErrorMsg(msg), arg1, arg2);
            }
        }

        public void remainError(String msg, Object argument)
        {
            if (realLogger.isErrorEnabled())
            {

                realLogger.error(formatRemainErrorMsg(msg), argument);
            }
        }

        public void remainError(String msg, Throwable t)
        {
            if (realLogger.isErrorEnabled())
            {

                realLogger.error(formatRemainErrorMsg(msg), t);
            }
        }

 
        
        
        public void trace(String msg, Object... arg)
        {
            if(realLogger.isTraceEnabled()) {
                realLogger.trace(formatMsg(msg), arg);
            }
        }

    }


    public enum Author{

        CODY("Cody","陈庚"),
        ;
        private String nick,name;
        public String nickname() {
            return nick;
        }
        public String realname() {
            return name;
        }
        private Author() {
            this.nick = this.name();
            this.name = this.name();
        }
        private Author(String name) {
            this(name,name);
        }
        private Author(String nick,String name) {
            this.name = name;this.nick = nick;
        }
    }


    /**
     * @Title cody
     * @Description 捷径方法：先把作者设为cody再打日志
     * @return
     */
    public LoggerWithAuthor cody()
    {
        this.author = Author.CODY;
        return (LoggerWithAuthor)this;
    }

    /**
     * @Title getLogger
     * @Description 取得自定义封装的Logger对象
     * @param clazz
     * @return
     */
    public static Logger getLogger(Class<?> clazz)
    {
        Logger logger = new LoggerWithAuthor();
        logger.realLogger = org.slf4j.LoggerFactory.getLogger(clazz);
        return logger;
    }

    /**
     * @Title getLogger
     * @Description 取得自定义封装的Logger对象 ，同时设定默认的作者。
     * @param clazz
     * @return
     */
    public static LoggerWithAuthor getLogger(Class<?> clazz, Author author)
    {
        LoggerWithAuthor logger = new LoggerWithAuthor();
        logger.realLogger = org.slf4j.LoggerFactory.getLogger(clazz);
        logger.author = author;
        return logger;
    }

    public void debug(String msg, Author author)
    {
        if (realLogger.isDebugEnabled())
        {

            this.author = author;

            realLogger.debug(formatMsg(msg));
        }
    }

    public void debug(String msg, Author author, Object... arguments)
    {
        if (realLogger.isDebugEnabled())
        {
            this.author = author;
            realLogger.debug(formatMsg(msg), arguments);
        }
    }

    public void debug(String msg, Author author, Object arg1, Object arg2)
    {
        if (realLogger.isDebugEnabled())
        {

            this.author = author;

            realLogger.debug(formatMsg(msg), arg1, arg2);
        }
    }

    public void debug(String msg, Author author, Object argument)
    {
        if (realLogger.isDebugEnabled())
        {
            this.author = author;
            realLogger.debug(formatMsg(msg), argument);
        }
    }

    public void debug(String msg, Author author, Throwable t)
    {
        if (realLogger.isDebugEnabled())
        {

            this.author = author;

            realLogger.debug(formatMsg(msg), t);
        }
    }

    public void info(String msg, Author author)
    {
        if (realLogger.isInfoEnabled())
        {

            this.author = author;

            realLogger.info(formatMsg(msg));
        }
    }

    public void info(String msg, Author author, Object... arguments)
    {
        if (realLogger.isInfoEnabled())
        {

            this.author = author;

            realLogger.info(formatMsg(msg), arguments);
        }
    }

    public void info(String msg, Author author, Object arg1, Object arg2)
    {
        if (realLogger.isInfoEnabled())
        {

            this.author = author;

            realLogger.info(formatMsg(msg), arg1, arg2);
        }
    }

    public void info(String msg, Author author, Object argument)
    {
        if (realLogger.isInfoEnabled())
        {

            this.author = author;

            realLogger.info(formatMsg(msg), argument);
        }
    }

    public void info(String msg, Author author, Throwable t)
    {
        if (realLogger.isInfoEnabled())
        {

            this.author = author;

            realLogger.info(formatMsg(msg), t);
        }
    }

    public void warn(String msg, Author author)
    {
        if (realLogger.isWarnEnabled())
        {

            this.author = author;

            realLogger.warn(formatMsg(msg));
        }
    }

    public void warn(String msg, Author author, Object... arguments)
    {
        if (realLogger.isWarnEnabled())
        {

            this.author = author;

            realLogger.warn(formatMsg(msg), arguments);
        }
    }

    public void warn(String msg, Author author, Object arg1, Object arg2)
    {
        if (realLogger.isWarnEnabled())
        {

            this.author = author;

            realLogger.warn(formatMsg(msg), arg1, arg2);
        }
    }

    public void warn(String msg, Author author, Object argument)
    {
        if (realLogger.isWarnEnabled())
        {

            this.author = author;

            realLogger.warn(formatMsg(msg), argument);
        }
    }

    public void warn(String msg, Author author, Throwable t)
    {
        if (realLogger.isWarnEnabled())
        {

            this.author = author;

            realLogger.warn(formatMsg(msg), t);
        }
    }

    public void error(String msg, Author author)
    {
        if (realLogger.isErrorEnabled())
        {

            this.author = author;

            realLogger.error(formatMsg(msg));
        }
    }

    public void error(String msg, Author author, Object... arguments)
    {
        if (realLogger.isErrorEnabled())
        {

            this.author = author;

            realLogger.error(formatMsg(msg), arguments);
        }
    }

    public void error(String msg, Author author, Object arg1, Object arg2)
    {
        if (realLogger.isErrorEnabled())
        {

            this.author = author;

            realLogger.error(formatMsg(msg), arg1, arg2);
        }
    }

    public void error(String msg, Author author, Object argument)
    {
        if (realLogger.isErrorEnabled())
        {

            this.author = author;

            realLogger.error(formatMsg(msg), argument);
        }
    }

    public void error(String msg, Author author, Throwable t)
    {
        if (realLogger.isErrorEnabled())
        {

            this.author = author;

            realLogger.error(formatMsg(msg), t);
        }
    }


}
